package br.ufrj.ppgi.infovis.forms;

import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.widgets.MTTextArea;
import org.mt4j.components.visibleComponents.widgets.MTTextField;
import org.mt4j.util.font.IFont;
import org.mt4j.util.font.IFontCharacter;

import processing.core.PApplet;

/**
 * <p>
 * This MTTextFieldVarLines allows a variable number of lines of text (up to
 * TEXT_FIELD_VAR_MAX_LINES) and adds a line break after each line has reached
 * the width of the TextField.
 * </p>
 * 
 * <p>
 * Extends the MT4j framework class MTTextArea, modification of the MT4j
 * framework class MTTextField (mt4j-desktop).
 * </p>
 * 
 * 
 * @see MTTextArea
 * @see MTTextField
 * 
 */
public class MTTextFieldVarLines extends MTTextArea {
    /* *** Text field variable lines constants *** */
    /** The text field width offset */
    protected static final int TEXT_FIELD_WIDTH_OFFSET  = 0;
    /** The maximum allowed number of lines */
    protected static final int TEXT_FIELD_VAR_MAX_LINES = 50;

    /* *** MTTextFieldVarLines *** */
    /** Flag that indicated if a clearing of the text field is currently active */
    private boolean            clearActive              = false;

    /** The maximum number of lines set at initialization */
    private int                maxNumberOfLines;

    /* ***********Constructors*********** */
    /**
     * Constructor. Instantiates a new MTTTextFieldTwoLines.
     * 
     * @param applet
     *            the application instance
     * @param x
     *            the x position of the var line text field
     * @param y
     *            the y position of the var line text field
     * @param width
     *            the width of the var line text field
     * @param height
     *            the height of the var line text field
     * @param maxNumberOfLines
     *            the maximum number of lines in the variable TextField
     * @param fontDefault
     *            the default font
     */
    public MTTextFieldVarLines(PApplet applet, float x, float y, float width,
            float height, int maxNumberOfLines, IFont fontDefault) {
        super(applet, x, y, width, height, fontDefault);
        // Set max number of lines
        this.setMaxNumberOfLines(maxNumberOfLines);
    }

    /* ********Getters & Setters******** */

    /**
     * Returns the max number of lines.
     * 
     * @return the maxNumberOfLines
     */
    public int getMaxNumberOfLines() {
        return this.maxNumberOfLines;
    }

    /**
     * Sets the max number of lines. If maxNumberOfLines >
     * TEXT_FIELD_VAR_MAX_LINES, the latter is set.
     * 
     * @param maxNumberOfLines
     *            the maxNumberOfLines to set
     */
    public void setMaxNumberOfLines(int maxNumberOfLines) {
        if (maxNumberOfLines > TEXT_FIELD_VAR_MAX_LINES) {
            this.maxNumberOfLines = TEXT_FIELD_VAR_MAX_LINES;
        } else {
            this.maxNumberOfLines = maxNumberOfLines;
        }
    }

    /**
     * Returns if clear currently active.
     * 
     * @return the clearActive
     */
    public boolean isClearActive() {
        return this.clearActive;
    }

    /* ********Overridden methods******** */
    /**
     * Method called after a character is added to the MTTextFieldVarLines (e.g.
     * via a keyboard). Checks which line we are in (max. lines is
     * maxNumberOfLines), begins a new line if necessary, removes added
     * character if we have reached the maxNumberOfLines limit.
     * 
     * @param character
     *            the added character
     * @see org.mt4j.components.visibleComponents.widgets.MTTextArea#characterAdded
     *      (org.mt4j.components.visibleComponents.font.IFontCharacter)
     */
    @Override
    protected void characterAdded(IFontCharacter character) {
        // Special handling of line breaks
        if (character.getUnicode().equalsIgnoreCase("\n")) { //$NON-NLS-1$
            // We still have more lines
            if (getLineCount() < this.maxNumberOfLines) {
                // Do nothing
            } else { // we are in "no more lines allowed" land, remove \n
                this.removeLastCharacter();
            }
        } else {
            // If we are still in the first line (getLineCount()==0)
            if (getLineCount() < (this.maxNumberOfLines - 1)) {
                // If the end of the line is reached,
                // start a new line with the new character
                float localWidth = this.getWidthXY(TransformSpace.LOCAL);
                localWidth += TEXT_FIELD_WIDTH_OFFSET;
                // We still have less than the maximum number of lines, so we
                // start a new line
                if (!this.clearActive && this.getText().length() > 0 && getLastCharEndPos() > localWidth) {
                    this.removeLastCharacter();
                    // Start new line and add character there
                    this.appendCharByUnicode("\n"); //$NON-NLS-1$
                    this.appendCharByUnicode(character.getUnicode());
                }
            } else { // We are in line maxNumberOfLines (or more, which should
                     // not be the case)
                float localWidth = this.getWidthXY(TransformSpace.LOCAL);
                localWidth += TEXT_FIELD_WIDTH_OFFSET;
                // If the end of the line is reached, don't add any characters
                if (this.getText().length() > 0 && getLastCharEndPos() > localWidth) {
                    // No more chars are to be added
                    this.removeLastCharacter();
                }
            }
        }
    }

    /**
     * Resets the text field, clears all characters.
     * 
     */
    @Override
    public void clear() {
        this.clearActive = true;
        int i = 0;
        while (super.getCharacters().length != 0) {
            i++;
            this.removeLastCharacter();
        }
        this.clearActive = false;
    }

    /* *********Utility methods********* */
    /**
     * Gets the last character end position.
     * 
     * @return the last character end position
     */
    protected float getLastCharEndPos() {
        return this.getMaxLineWidth() + this.getScrollTextX();
    }
}
